package cn.tedu.boot.demo.service.impl;

import cn.tedu.boot.demo.entity.Admin;
import cn.tedu.boot.demo.ex.*;
import cn.tedu.boot.demo.mapper.AdminMapper;
import cn.tedu.boot.demo.pojo.dto.AdminAddNewDTO;
import cn.tedu.boot.demo.pojo.dto.AdminLoginDTO;
import cn.tedu.boot.demo.pojo.vo.AdminSimpleVO;
import cn.tedu.boot.demo.service.IAdminService;
import cn.tedu.boot.demo.util.PasswordEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AdminMapper adminMapper;

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        // 日志
        log.trace("业务逻辑层：AdminServiceImpl.addNew() >>> 开始添加管理员业务");
        log.debug("尝试添加的管理员账号信息：" + adminAddNewDTO);
        // 通过参数获取用户名
        log.trace("判断此账号是否已经被占用");
        String username = adminAddNewDTO.getUsername();
        // 调用adminMapper的Admin getByUsername(String username)方法执行查询
        AdminSimpleVO queryResult = adminMapper.getByUsername(username);
        // 判断查询结果是否不为null
        if (queryResult != null) {
            // 是：表示用户名已经被占用，则抛出UsernameDuplicateException
            log.error("此账号已经被占用，将抛出异常");
            throw new UsernameDuplicateException("添加管理员失败，用户名（" + username + "）已经被占用！");
        }

        // 日志
        log.trace("此账号未被占用，准备向表中写入此次添加的管理员信息");
        // 通过参数获取原密码
        String password = adminAddNewDTO.getPassword();
        //log.debug("原密码=" + password);
        // 通过加密方式，得到加密后的密码encodedPassword
        String encodedPassword = passwordEncoder.encode(password);
        //log.debug("加密后的密码=" + encodedPassword);
        log.debug("加密前的密码：{}，加密后的密码：{}", password, encodedPassword);
        log.debug("加密前的密码：" + password + "，加密后的密码：" + encodedPassword);

        // 创建当前时间对象now > LocalDateTime.now()
        LocalDateTime now = LocalDateTime.now();

        // 创建Admin对象
        Admin admin = new Admin();
        // 补全Admin对象的属性值：通过参数获取username,nickname……
        admin.setUsername(username);
        admin.setNickname(adminAddNewDTO.getNickname());
        admin.setAvatar(adminAddNewDTO.getAvatar());
        admin.setPhone(adminAddNewDTO.getPhone());
        admin.setEmail(adminAddNewDTO.getEmail());
        admin.setDescription(adminAddNewDTO.getDescription());
        // 以上这些从一个对象中把属性赋到另一个对象中，还可以使用：
        // BeanUtils.copyProperties(adminAddNewDTO, admin);
        // 补全Admin对象的属性值：password > encodedPassword
        admin.setPassword(encodedPassword);
        // 补全Admin对象的属性值：isEnable > 1
        admin.setIsEnable(1);
        // 补全Admin对象的属性值：lastLoginIp > null
        // 补全Admin对象的属性值：loginCount > 0
        admin.setLoginCount(0);
        // 补全Admin对象的属性值：gmtLastLogin > null
        // 补全Admin对象的属性值：gmtCreate > now
        admin.setGmtCreate(now);
        // 补全Admin对象的属性值：gmtModified > now
        admin.setGmtModified(now);
        // 调用adminMapper的insert(Admin admin)方法插入管理员数据，获取返回值
        log.debug("即将插入新的管理员信息：{}", admin);
        int rows = adminMapper.insert(admin);

        // 判断以上返回的结果是否不为1，抛出InsertException异常
        if (rows != 1) {
            throw new InsertException("添加管理员失败，服务器忙，请稍后再次尝试！");
        }
    }

    @Override
    public AdminSimpleVO login(AdminLoginDTO adminLoginDTO) {
        // 日志
        log.debug("即将处理管理员登录的业务，尝试登录的管理员信息：{}", adminLoginDTO);
        log.debug("第1步：判断用户名是否存在");
        // 通过参数得到尝试登录的用户名
        String username = adminLoginDTO.getUsername();
        // 调用adminMapper.getByUsername()方法查询
        AdminSimpleVO queryResult = adminMapper.getByUsername(username);
        // 判断查询结果是否为null
        if (queryResult == null) {
            // 是：表示用户名不存在，则抛出UserNotFoundException异常
            log.warn("登录失败，用户名不存在！");
            throw new UserNotFoundException("登录失败，用户名不存在！");
        }

        // 【如果程序可以执行到此步，则可以确定未抛出异常，即查询结果不为null】
        // 【以下可视为：存在与用户名匹配的管理员数据】
        // 判断查询结果中的isEnable属性值是否不为1
        log.debug("第2步：判断用户名是否存在此账号是否处于启用状态");
        if (queryResult.getIsEnable() != 1) {
            // 是：表示此用户状态是【禁用】的，则抛出UserStateException异常
            log.warn("登录失败，此账号已经被禁用！");
            throw new UserStateException("登录失败，此账号已经被禁用！");
        }

        // 【如果程序可以执行到此步，表示此用户状态是【启用】的】
        // 从参数中取出此次登录时客户端提交的密码
        log.debug("第3步：判断密码是否正确");
        String rawPassword = adminLoginDTO.getPassword();
        // 调用PasswordEncoder对象的matches()方法，对客户端提交的密码和查询结果中的密码进行验证
        boolean matchResult = passwordEncoder.matches(rawPassword, queryResult.getPassword());
        // 判断以上验证结果
        if (!matchResult) {
            // false：密码错误，视为登录失败，则抛出PasswordNotMatchException异常
            log.warn("登录失败，密码错误！");
            throw new PasswordNotMatchException("登录失败，密码错误！");
        }

        // 密码正确，视为登录成功
        // 将查询结果中的password、isEnable设置为null，避免响应到客户端
        queryResult.setPassword(null);
        queryResult.setIsEnable(null);
        // 返回查询结果
        log.debug("登录成功，即将返回：{}", queryResult);
        return queryResult;
    }

}
